package models

import (
	"cloudops/src/config"
	"github.com/casbin/casbin/v2"
	"github.com/casbin/casbin/v2/model"
	gormadapter "github.com/casbin/gorm-adapter/v3"
	"go.uber.org/zap"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
)

var (
	DB             *gorm.DB
	casbinEnforcer *casbin.Enforcer
)

// 初始化数据库连接
func InitDb(sc *config.ServerConfig) error {
	db, err := gorm.Open(
		mysql.Open(sc.MySqlC.DSN),

		// gorm 打印sql日志 开发模式使用
		&gorm.Config{Logger: logger.Default.LogMode(logger.Info)},

		// gorm 打印sql日志 生产模式使用
		//&gorm.Config{Logger: logger.Default.LogMode(logger.Silent)},
	)

	if err != nil {
		return err
	}
	DB = db
	return nil
}

// 初始化casbin权限管理
func InitCasbin(sc *config.ServerConfig) error {
	a, err := gormadapter.NewAdapterByDB(DB)
	if err != nil {
		sc.Logger.Error("初始化casbin数据库错误", zap.Error(err))
		return err
	}
	// 初始化模型
	modelText := `
	[request_definition]
	r = sub, obj, act
	
	[policy_definition]
	p = sub, obj, act
	
	[role_definition]
	g = _, _
	
	[policy_effect]
	e = some(where (p.eft == allow))
	
	[matchers]
	m = r.sub == p.sub && keyMatch2(r.obj,p.obj) && r.act == p.act
    `
	m, err := model.NewModelFromString(modelText)
	if err != nil {
		sc.Logger.Error("casbin字符串加载模型失败!", zap.Error(err))
		return err
	}

	casbinEnforcer, err = casbin.NewEnforcer(m, a)
	if err != nil {
		sc.Logger.Error("casbin创建Enforcer失败!", zap.Error(err))
		return err
	}
	return nil
}

// MigrateTable 自动迁移数据库表
func MigrateTable() error {
	return DB.AutoMigrate(
		// 底座相关模型
		&User{},
		&Role{},
		&Menu{},
		&Api{},

		// 服务树和 CMDB 模型
		&StreeNode{},
		&ResourceEcs{},
		&ResourceElb{},
		&ResourceRds{},

		// 工单相关模型
		&Process{},
		&FlowNode{},
		&FormDesign{},
		&WorkOrderTemplate{},
		&WorkOrderInstance{},

		// 任务执行相关模型
		&JobScript{},
		&JobTask{},
		&JobResult{},

		//// Prometheus 监控相关模型
		//&MonitorScrapePool{},
		//&MonitorScrapeJob{},
		//&MonitorAlertmanagerPool{},
		//&MonitorSendGroup{},
		//&MonitorAlertRule{},
		//&MonitorAlertEvent{},
		//&MonitorRecordRule{},
		//
		//&MonitorOndutyGroup{},   // 值班相关模型
		//&MonitorOndutyHistory{}, // 值班历史记录模型
		//&MonitorOndutyChange{},  // 值班变更记录模型
		//
		//// K8s 相关模型
		//&K8sCluster{},
		//&K8sYamlTemplate{},
		//&K8sYamlTask{},
		//&K8sProject{},
		//&K8sApp{},
		//&K8sInstance{},
		//&K8sCronjob{},
		//
		//// CI/CD 相关模型
		//&CicdDeployItem{},
		//&CicdWorkOrder{},
		//&CicdDeployStageStatus{},
	)
}

// 分离数据和mock数据
func InsertBasicDbData(sc *config.ServerConfig) {
	// 基础数据 user role menu api
	//start := time.Now()

	/*	MockBasicData(sc)
			sc.Logger.Info("计算mock时间", zap.Any("模块", "[01 底座]"), zap.Duration("耗时", time.Since(start)))

			MockCmdbTree(sc)
			sc.Logger.Info("计算mock时间", zap.Any("模块", "[02 服务树]"), zap.Duration("耗时", time.Since(start)))

			MockWorkOrder(sc)
			sc.Logger.Info("计算mock时间", zap.Any("模块", "[03 工单]"), zap.Duration("耗时", time.Since(start)))

		MockJobExec(sc)
		sc.Logger.Info("计算mock时间", zap.Any("模块", "[04 任务执行]"), zap.Duration("耗时", time.Since(start)))
	*/
	//MockMonitor(sc)
	//sc.Logger.Info("计算mock时间", zap.Any("模块", "[05 Prometheus]"), zap.Duration("耗时", time.Since(start)))

	//MockK8s(sc)
	//sc.Logger.Info("计算mock时间", zap.Any("模块", "[06 k8s]"), zap.Duration("耗时", time.Since(start)))

	//MockCicd(sc)
	//sc.Logger.Info("计算mock时间", zap.Any("模块", "[07 cicd]"), zap.Duration("耗时", time.Since(start)))

}
